import { HttpMethod, ResponseData } from '@/types/type'
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
import { ElMessage } from 'element-plus'

const createAxios = (config?: AxiosRequestConfig<any>): AxiosInstance => {
    //创建Axios实例
    const axiosInstance = axios.create({
        ...config,
        baseURL: import.meta.env.VITE_APP_BASE_API,
        timeout: 10000,
    })
    // 请求拦截器
    axiosInstance.interceptors.request.use(
        (config) => {
            const { admin } = useAdminStore()
            if (config.headers) {
                const token = admin.accessToken
                if (token) config.headers.Authorization = `Bearer ` + token
            }
            return config
        },
        (error) => {
            return Promise.reject(error)
        },
    )
    // 是否正在刷新token
    let isRefreshTokening = false
    //响应拦截器
    axiosInstance.interceptors.response.use(
        (response) => {
            // 如果是导出文件返回response，否则返回response.data
            if (config && config.responseType === 'blob') {
                return response
            } else {
                return response.data
            }
        },
        async (error) => {
            if (error.response && error.response.status === 401) {
                const { admin, setToken, adminUserLogout } = useAdminStore()

                // 如果token或者刷新token不存在，直接退出登录
                if (!admin.accessToken || !admin.refreshToken || !isRefreshTokening) {
                    adminUserLogout()
                    goLogin()
                } else {
                    isRefreshTokening = true
                    // 请求失败的Authorization
                    const auth = error.config.headers.Authorization
                    // 刷新token
                    const result = await refreshToken(admin.refreshToken)
                    isRefreshTokening = false
                    // 刷新失败，退出登录
                    if (!result.isSuccess) {
                        adminUserLogout()
                        goLogin()
                    } else {
                        // 刷新后的新token
                        const accessToken = result.data
                        // 替换掉旧的token
                        setToken(accessToken)
                        // 刷新成功后的Authorization
                        const refreshAuth = `Bearer ` + accessToken
                        // 如果刷新成功后的Authorization与请求失败的Authorization不是一个，则重新发起上次失败的请求
                        if (auth !== refreshAuth) {
                            try {
                                error.config.headers.Authorization = refreshAuth
                                return await axiosInstance(error.config)
                            } catch (error) {
                                adminUserLogout()
                                goLogin()
                            }
                        } else {
                            adminUserLogout()
                            goLogin()
                        }
                    }
                }
            }
            // 向用户提示错误原因
            responseErrorHandle(error)
            return Promise.reject(error)
        },
    )

    return axiosInstance
}

export default createAxios

/**
 * 请求方法
 * @param url 请求地址
 * @param method 请求方法
 * @param data 请求体参数
 * @param params QueryString参数
 * @param config 默认axios请求配置
 * @returns
 */
export async function request<T>(
    url: string,
    method?: HttpMethod,
    data?: any,
    params?: any,
    config?: AxiosRequestConfig<any>,
): Promise<ResponseData<T>> {
    if (!method) method = 'GET'
    return await createAxios(config).request({
        url,
        method,
        data,
        params,
    })
}
/**
 * 跳转到登录页
 */
const goLogin = () => {
    const tabs = useTabsStore()
    router.push({ path: '/login', query: { redirect: tabs.tabs.activetabPath } })
    window.location.reload()
}

/**
 * 响应错误处理
 * @param error 响应错误
 * @returns
 */
const responseErrorHandle = (error: any) => {
    // 处理被取消的请求
    if (axios.isCancel(error)) return console.error('因为请求重复被自动取消：' + error.message)

    // 定义一个变量，存储网络信息错误
    let message = ''

    if (error && error.response) {
        // http状态码
        const status = error.response.status
        switch (status) {
            case 302:
                message = '接口重定向了！'
                break
            case 400:
                message = '请求参数不正确！'
                break
            case 401:
                message = '登录已过期！'
                break
            case 403:
                message = '您没有权限操作！'
                break
            case 404:
                message = '请求地址出错:' + error.response.config.url
                break
            case 405:
                message = '请求方式错误！'
                break
            case 408:
                message = '请求超时！'
                break
            case 409:
                message = '数据正在使用中，不能执行当前操作！'
                break
            case 500:
                message = '服务器异常！'
                break
            case 501:
                message = '服务未实现！'
                break
            case 502:
                message = '网关错误！'
                break
            case 503:
                message = '服务不可用！'
                break
            case 504:
                message = '网关超时！'
                break
            case 505:
                message = 'HTTP协议版本不受支持！'
                break
            default:
                message = '请求失败，请联系网站管理员！'
                break
        }
    }

    if (error.message.includes('timeout')) message = ' 网络请求超时！'
    if (error.message.includes('Network')) message = window.navigator.onLine ? '服务端异常！' : '网络未连接'

    //提示错误信息
    ElMessage.error(message)
}
